'''  
 己方棋子编码约定:														
	1司令,2军长,3师长,4旅长,5团长,6营长,7连长,8排长,9工兵,10地雷，11炸弹,12军旗      
 对方方棋子编码约定:
    14军旗 13未知对方棋子
    0空棋位
'''

import eneSta


# i,j位置是否本方棋子
def IsMyChess(i, j, cMap):
    # 通过cMap的my_chess_list查询该位置是不是我方棋子
    if (i, j) in cMap.my_chess_list:
        return 1
    else:
        return 0


# 是否为敌方棋子
def IsEneChess(i, j, cMap):
    # 通过cMap的ene_chess_list查询该位置是不是敌方棋子
    if (i, j) in cMap.ene_chess_list:
        return 1
    else:
        return 0

# i,j位置是否本方可移动的棋子
def IsMyMovingChess(i, j, cMap):
    if not IsMyChess(i, j, cMap): # 首先判断是不是我方棋子
        return 0
    if cMap.map[i][j] >= 1 and cMap.map[i][j] <= 9 or cMap.map[i][j] == 11:  # warning :crossline?
        return 1
    else:
        return 0


# 是否为敌方可移动棋子 未翻译

def IsAfterHill(i, j):
    if i * 5 + j == 31 or i * 5 + j == 33:
        return 1
    else:
        return 0


def IsBeforeHill(i, j):
    if (i * 5 + j == 26 or i * 5 + j == 28):
        return 1
    else:
        return 0


def IsMoveCamp(i, j):
    if i * 5 + j == 11 or i * 5 + j == 13 or i * 5 + j == 17 or i * 5 + j == 21 or i * 5 + j == 23 or i * 5 + j == 36 or i * 5 + j == 38 or i * 5 + j == 42 or i * 5 + j == 46 or i * 5 + j == 48:
        return 1
    else:
        return 0


def IsMyMoveCamp(i, j):
    if i * 5 + j == 36 or i * 5 + j == 38 or i * 5 + j == 42 or i * 5 + j == 46 or i * 5 + j == 48:
        return 1
    else:
        return 0


def IsEnemyMoveCamp(i, j):
    if i * 5 + j == 11 or i * 5 + j == 13 or i * 5 + j == 17 or i * 5 + j == 21 or i * 5 + j == 23:
        return 1
    else:
        return 0


# i,j位置是否大本营
def IsBaseCamp(i, j):
    if i * 5 + j == 1 or i * 5 + j == 3 or i * 5 + j == 56 or i * 5 + j == 58:
        return 1
    else:
        return 0


def IsMyBaseCamp(i, j):
    if i * 5 + j == 56 or i * 5 + j == 58:
        return 1
    else:
        return 0


def IsEnemyBaseCamp(i, j):
    if i * 5 + j == 1 or i * 5 + j == 3:
        return 1
    else:
        return 0


# i,j位置是否有棋子占位的行营
def IsFilledCamp(i, j, cMap):
    if IsMoveCamp(i, j) and cMap.map[i][j] != 0:  # warn: crossline
        return 1
    else:
        return 0


# i,j位置是否有铁路
def IsAcrossRailway(i):
    if i == 1 or i == 5 or i == 6 or i == 10:
        return 1
    else:
        return 0


def IsVerticalRailway(i, j):
    if (j == 0 or j == 4) and (i > 0 and i < 11):
        return 1
    else:
        return 0


def IsEngineerRailway(i, j):
    if j == 2 and (i == 5 or i == 6):
        return 1
    else:
        return 0


def shortestpathtojunqi(i, j):
    return abs(11 - i) + abs(3 - j)


# 未考虑斜向路线

def getNearPos(i, j):
    result = []
    if i > 0 and not (IsAfterHill(i, j)):
        result.append((i - 1, j))
    # 可以左移
    if (j > 0):
        result.append((i, j - 1))
    # 可以右移
    if (j < 4):
        result.append((i, j + 1))
    # 可以后移
    if (i < 11 and not (IsBeforeHill(i, j))):
        result.append((i + 1, j))
    # 可以左上进行营
    if (IsMoveCamp(i - 1, j - 1)):
        result.append((i - 1, j - 1))
    # 可以右上进行营
    if (IsMoveCamp(i - 1, j + 1)):
        result.append((i - 1, j + 1))
    # 可以左下进行营
    if (IsMoveCamp(i + 1, j - 1)):
        result.append((i + 1, j - 1))
    # 可以右下进行营
    if (IsMoveCamp(i + 1, j + 1)):
        result.append((i + 1, j + 1))
    if (IsMoveCamp(i, j)):
        result.append((i - 1, j - 1))
        result.append((i - 1, j + 1))
        result.append((i + 1, j - 1))
        result.append((i + 1, j + 1))
    return result


def IsEneMovingChess(i, j, cMap):
    '''

    :param i:敌方棋子坐标
    :param j:敌方棋子坐标
    :param cMap:
    :return:如果敌方棋子是地雷或者军旗返回0（不可移动） 其他返回1（可以移动）
    '''
    ene_chess = cMap.ene_map[cMap.map[i][j]]
    if ene_chess == 10 or ene_chess == 12:
        return 0
    else:
        return 1


def getAccessibility(i, j, isEne, cMap):
    result = []
    if isEne:
        # 如果是敌方棋子 获取cMap上面的编号，查询敌方棋子类型

        isMovingChess = IsEneMovingChess
        isChess = IsEneChess
        isInvChess = IsMyChess
    else:
        isMovingChess = IsMyMovingChess
        isChess = IsMyChess
        isInvChess = IsEneChess
    #if (isMovingChess(i, j, posList, cMap) and not (IsBaseCamp(i, j))) or (i==2 and j==2 and not(IsBaseCamp(i, j))):  # 己方不在大本营的可移动棋子
    if (isMovingChess(i, j, cMap) and not (IsBaseCamp(i, j))) :  # 己方不在大本营的可移动棋子
        y2 = i
        x2 = j
        # 可以前移:不在第一行,不在山界后,前方不是己方棋子,前方不是有棋子占领的行营
        if (i > 0 and not (IsVerticalRailway(i, j)) and not (IsAfterHill(i, j)) and not (isChess(i - 1, j, cMap))
                and not (IsFilledCamp(i - 1, j, cMap))):#不是铁路的前进方式
            y2 = i - 1
            result.append((y2, x2))
        else:
            k=1#是铁路的前进方式
            while (y2 > 0 and y2 < 11 and IsVerticalRailway(y2, x2) and IsVerticalRailway(y2 - 1, j) and not (
                IsAfterHill(y2, j)) and not (isChess(y2 - 1, j, cMap)) and not (IsFilledCamp(y2 - 1, j, cMap))):
                y2 = i - k
                k += 1
                result.append((y2, x2))
                if isInvChess(y2, x2, cMap):  # 当前位置已经是敌方棋子，不能再前进
                    break

        y2 = i
        x2 = j
        # 可以左移:不在最左列,左侧不是己方棋子,左侧不是被占用的行营
        if j > 0 and not (IsAcrossRailway(i)) and not (isChess(i, j - 1, cMap)) and not (IsFilledCamp(i, j - 1, cMap)):#不在铁路上
            x2 = j - 1
            result.append((y2, x2))
        else:
            k=1
            while x2 > 0 and IsAcrossRailway(i) and not (isChess(i, x2 - 1, cMap)) and not (IsFilledCamp(i, x2 - 1, cMap)):
                x2 = j - k
                k += 1
                result.append((y2, x2))
                if isInvChess(y2, x2, cMap):
                    break

        y2 = i
        x2 = j
        # 可以右移:不在最右列,右侧不是己方棋子,右侧不是被占用的行营
        if j < 4 and not (IsAcrossRailway(i)) and not (isChess(i, j + 1, cMap)) and not (IsFilledCamp(i, j + 1, cMap)):
            x2 = j + 1
            result.append((y2, x2))
        else:
            k=1
            while x2 < 4 and IsAcrossRailway(i) and not (isChess(i, x2 + 1, cMap)) and not (IsFilledCamp(i, x2 + 1, cMap)):
                x2 = j + k
                k += 1
                result.append((y2, x2))
                if isInvChess(y2, x2, cMap):
                    break

        y2 = i
        x2 = j
        # 可以后移:不在最后列,不在山界前,后侧不是己方棋子,后侧不是被占用的行营
        if (i < 11 and not (IsVerticalRailway(i, j)) and not (IsBeforeHill(i, j)) and not (isChess(i + 1, j, cMap))
                and not (IsFilledCamp(i + 1, j, cMap))):
            y2 = i + 1
            result.append((y2, x2))
        else:
            k=1
            while (y2 < 11 and y2 > 0 and IsVerticalRailway(y2, x2) and IsVerticalRailway(y2 + 1, j)
                and not (IsBeforeHill(y2, j)) and not (isChess(y2 + 1, j, cMap)) and not (IsFilledCamp(y2 + 1, j, cMap))):
                y2 = i + k
                result.append((y2, x2))
                k += 1
                if isInvChess(y2, x2, cMap):# 当前位置已经是敌方棋子，不能再前进
                    break

        # 后面不用更新x2 y2的值了，因为都是现场计算的
        # 可以左上进行营:左上不是被占用的行营且它是行营
        if IsMoveCamp(i - 1, j - 1) and not (IsFilledCamp(i - 1, j - 1, cMap)):
            y2 = i - 1
            x2 = j - 1
            result.append((y2, x2))

        # 可以右上进行营:右上不是被占用的行营且它是行营
        if IsMoveCamp(i - 1, j + 1) and not (IsFilledCamp(i - 1, j + 1, cMap)):
            y2 = i - 1
            x2 = j + 1
            result.append((y2, x2))

        # 可以左下进行营:左下不是被占用的行营且它是行营
        if IsMoveCamp(i + 1, j - 1) and not (IsFilledCamp(i + 1, j - 1, cMap)):
            y2 = i + 1
            x2 = j - 1
            result.append((y2, x2))

        # 可以右下进行营:右下不是被占用的行营且它是行营
        if IsMoveCamp(i + 1, j + 1) and not (IsFilledCamp(i + 1, j + 1, cMap)):
            y2 = i + 1
            x2 = j + 1
            result.append((y2, x2))

        # 可以左上出行营:目前位置为行营且左上不是己方棋子
        if IsMoveCamp(i, j) and not (isChess(i - 1, j - 1, cMap)):
            if not ((IsMoveCamp(i - 1, j - 1)) and IsFilledCamp(i - 1, j - 1, cMap)):  # 如果是行营行营里不能有子
                y2 = i - 1
                x2 = j - 1
                result.append((y2, x2))

        # 可以右上出行营:目前位置为行营且右上不是己方棋子
        if IsMoveCamp(i, j) and not (isChess(i - 1, j + 1, cMap)):
            if not ((IsMoveCamp(i - 1, j + 1)) and IsFilledCamp(i - 1, j + 1, cMap)):
                y2 = i - 1
                x2 = j + 1
                result.append((y2, x2))

        # 可以左下出行营:目前位置为行营且左下不是己方棋子
        if IsMoveCamp(i, j) and not isChess(i + 1, j - 1, cMap):
            if not (IsMoveCamp(i + 1, j - 1) and IsFilledCamp(i + 1, j - 1, cMap)):
                y2 = i + 1
                x2 = j - 1
                result.append((y2, x2))

        # 可以右下出行营:目前位置为行营且右下不是己方棋子
        if IsMoveCamp(i, j) and not (isChess(i + 1, j + 1, cMap)):
            if not (IsMoveCamp(i + 1, j + 1) and IsFilledCamp(i + 1, j + 1, cMap)):
                y2 = i + 1
                x2 = j + 1
                result.append((y2, x2))
    return result

# 概率表棋子对应下标
siling = 9
junzhang = 8
shizhang = 7
lvzhang = 6
tuanzhang = 5
yingzhang = 4
lianzhang = 3
paizhang = 2
gongbing = 1
junqi = 0
dilei = 10
zhadan = 11


def findJunqi(probTable):
    for i in range(12):
        nowList = probTable[i]
        if not nowList[junqi] > 0.5:  # 军棋位非0
            isFind = True
            for j in range(1, 12):
                if nowList[j] > 0.5:  # 只允许一个非0
                    isFind = False
                    break
            if isFind:
                return i
    return -1


usBeatHand = None  # 我方上次吃子手数
eneBeatHand = None  # 敌方上次吃子手数
handNum = None  # 目前手数
_maxMoveNum = 31  # 最大不吃子次数

def get_action_list(isEne, cMap):
    """
    给出所有可移动棋子的坐标列表
    :param isEne:
    :param cMap:
    :return:
    """
    chess_list = []
    if isEne:
        for i in range(len(cMap.ene_chess_list)):
            x, y = cMap.ene_chess_list[i]
            action_list = getAccessibility(x, y, isEne, cMap)
            if len(action_list) > 0:
                chess_list.append((x, y))
        # print('ene chess list', chess_list)

    else:
        for i in range(len(cMap.my_chess_list)):
            x, y = cMap.my_chess_list[i]
            action_list = getAccessibility(x, y, isEne, cMap)
            if len(action_list) > 0:
                chess_list.append((x, y))
        #  print(list)
    return chess_list

def game_end(cMap, move_num):
    """
    判断游戏是不是结束  判断是不是达到摩奇上限或者双方军旗被吃或者一方没有可以移动的棋子
    :param cMap:
    :param move_num: 磨棋次数
    :return: True：游戏结束 FALSE：游戏继续
    """
    max_move = 30
    #  是不是达到磨棋上限
    if max_move <= move_num :
        #print('磨棋结束')
        return True

    # 有没有可移动棋子
    my_action_list = get_action_list(False, cMap)
    ene_action_list = get_action_list(True, cMap)
    if len(my_action_list) == 0 or len(ene_action_list) == 0:
        #print('没有行动棋子结束')
        return True

    # 双方军旗是否被吃掉
    if cMap.ene_map[cMap.map[0, 1]] != 12 and cMap.ene_map[cMap.map[0, 3]] != 12:
        # 敌方行营没有一个位置是军旗
        #print('敌方没有棋子是军旗结束')
        return True

    if cMap.map[11, 1] != 12 and cMap.map[11, 3] != 12:
        # 我方行营没有一个位置是军旗
        #print('我方没有棋子是军旗结束')
        return True

    #  三个终局条件都不满足，游戏继续进行
    return False
